package com.ballball.matchingsystem.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

@Component
public class MatchingPool extends Thread{
    private static List<Player> players=new ArrayList<>();
    // 存储邀请关系，用于快速匹配邀请好友
    private static Map<Integer, Integer> inviteRelations = new HashMap<>();
    private final ReentrantLock lock=new ReentrantLock();
    private static RestTemplate restTemplate;

    private final static String startGameUrl="http://ball-backend:3000/pk/start/game/";
    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        MatchingPool.restTemplate = restTemplate;
    }//利用这个将sendresult发送到backend

    public void addPlayer(Integer userId,Integer rating){
        lock.lock();
        try {
            // 先检查用户是否已在匹配池中
            if (!isPlayerInPool(userId)) {
                players.add(new Player(userId,rating,0));
                System.out.println("添加用户到匹配池: " + userId);
            } else {
                System.out.println("用户已在匹配池中，忽略添加: " + userId);
            }
        }finally {
            lock.unlock();
        }
    }

    public void removePlayer(Integer userId){
        lock.lock();
        try {
            List<Player> newPlayers=new ArrayList<>();
            for (Player player:players){
                if (!player.getUserId().equals(userId)){
                    newPlayers.add(player);
                }// 如果当前用户不是要删除的玩家，则添加到新的玩家列表中
            }
            players=newPlayers;// 更新玩家列表,删除当前用户
            
            // 移除邀请关系
            inviteRelations.entrySet().removeIf(entry -> entry.getKey().equals(userId) || entry.getValue().equals(userId));
        }finally {
            lock.unlock();
        }
    }

    // 添加好友邀请关系
    public void addInviteRelation(Integer inviterId, Integer inviteeId) {
        lock.lock();
        try {
            inviteRelations.put(inviterId, inviteeId);
            System.out.println("添加邀请关系: " + inviterId + " -> " + inviteeId);
        } finally {
            lock.unlock();
        }
    }
    
    //辅助函数
    private void increaseWaitingTime(){// 增加等待时间,每个玩家等待时间加一
        for (Player player:players){
            player.setWaitingTime(player.getWaitingTime()+1);
        }
    }

    private boolean checkMatched(Player a, Player b, Player c) {// 检查三个玩家是否匹配
        // 计算三个玩家之间的最大rating差值
        int deltaAB = Math.abs(a.getRating() - b.getRating());
        int deltaAC = Math.abs(a.getRating() - c.getRating());
        int deltaBC = Math.abs(b.getRating() - c.getRating());
        int maxDelta = Math.max(deltaAB, Math.max(deltaAC, deltaBC));

        // 取三个玩家的最大等待时间
        int maxWaitingTime = Math.max(a.getWaitingTime(),
                Math.max(b.getWaitingTime(), c.getWaitingTime()));

        // 当最大分差 <= 最大等待时间*10 时匹配成功
        return maxDelta <= maxWaitingTime * 10;
    }

    private void sendResult(Player a,Player b,Player c){//返回匹配结果
        System.out.println("send result: "+a.getUserId()+" "+b.getUserId()+" "+c.getUserId());
        MultiValueMap<String, String> data=new LinkedMultiValueMap<>();
        data.add("a_id",a.getUserId().toString());
        data.add("b_id",b.getUserId().toString());
        data.add("c_id",c.getUserId().toString());
        restTemplate.postForObject(startGameUrl,data,String.class);
    }

    private void matchPlayers(){//尝试匹配玩家
        System.out.println("match players:"+players.toString());
        boolean[] used=new boolean[players.size()];
        
        // 先处理好友邀请关系，优先匹配邀请的好友
        for (int i = 0; i < players.size(); i++) {
            Integer playerId = players.get(i).getUserId();
            
            // 检查是否是邀请者
            if (inviteRelations.containsKey(playerId)) {
                Integer inviteeId = inviteRelations.get(playerId);
                
                // 检查被邀请者是否在匹配池中
                int inviteeIndex = -1;
                for (int j = 0; j < players.size(); j++) {
                    if (players.get(j).getUserId().equals(inviteeId)) {
                        inviteeIndex = j;
                        break;
                    }
                }
                
                // 如果邀请者和被邀请者都在匹配池中，尝试为他们匹配第三人
                if (inviteeIndex != -1 && !used[i] && !used[inviteeIndex]) {
                    Player a = players.get(i);
                    Player b = players.get(inviteeIndex);
                    
                    // 寻找适合的第三人
                    for (int k = 0; k < players.size(); k++) {
                        if (k != i && k != inviteeIndex && !used[k]) {
                            Player c = players.get(k);
                            // 检查三人是否匹配，对于好友组合，可以放宽匹配条件
                            if (checkFriendMatch(a, b, c)) {
                                used[i] = used[inviteeIndex] = used[k] = true;
                                sendResult(a, b, c);
                                // 移除匹配的邀请关系
                                inviteRelations.remove(playerId);
                                break;
                            }
                        }
                    }
                }
            }
        }
        
        // 常规匹配逻辑
        for (int i=0;i<players.size();i++){
            if(used[i]) continue;
            for (int j=i+1;j<players.size();j++){
                if(used[j]) continue;
                for (int k=j+1;k<players.size();k++) {
                    if (used[k]) continue;

                    Player a = players.get(i), b = players.get(j), c = players.get(k);
                    // 修改判断条件为三人版本
                    if (checkMatched(a, b, c)) {
                        used[i] = used[j] = used[k] = true;
                        sendResult(a, b, c);
                    }
                }
            }
        }
        // 将匹配成功的玩家从players中删除
        List<Player> newPlayers=new ArrayList<>();
        for (int i=0;i<players.size();i++){
            if(!used[i]){
                newPlayers.add(players.get(i));
            }
        }
        players=newPlayers;
        
        // 更新邀请关系，移除已经匹配的玩家
        inviteRelations.entrySet().removeIf(entry -> 
            !isPlayerInPool(entry.getKey()) || !isPlayerInPool(entry.getValue()));
    }
    
    // 为好友匹配添加的更宽松的匹配条件
    private boolean checkFriendMatch(Player a, Player b, Player c) {
        // 为好友匹配提供更宽松的条件
        int deltaAB = Math.abs(a.getRating() - b.getRating());
        int deltaAC = Math.abs(a.getRating() - c.getRating());
        int deltaBC = Math.abs(b.getRating() - c.getRating());
        int maxDelta = Math.max(deltaAB, Math.max(deltaAC, deltaBC));
        
        // 好友之间的匹配条件更宽松，可以有更大的分差
        return maxDelta <= 300; // 更大的分差值
    }
    
    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(1000);
                lock.lock();
                try {
                    increaseWaitingTime();
                    matchPlayers();//这二个函数都会改变players,所以要加锁
                }finally {
                    lock.unlock();
                }
            }catch (InterruptedException e){
                e.printStackTrace();
                break;
            }
        }
    }

    // 新增方法：检查用户当前是否已经在匹配池中
    public boolean isPlayerInPool(Integer userId) {
        lock.lock();
        try {
            for (Player player : players) {
                if (player.getUserId().equals(userId)) {
                    return true;
                }
            }
            return false;
        } finally {
            lock.unlock();
        }
    }
}
